package com.service.api;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.service.bean.device.Vehicle;
import com.service.bean.signal.GpsSignal;
import com.service.bean.signal.GpsSignalPath;
import com.service.cache.CacheManager;
import com.service.db.DbManager;
import com.service.other.Logger;
import com.service.other.ServerConfig;
import com.service.tools.Tools;

/**
 * 百度补点
 * 
 * @author lj
 * 
 */
public class BaiduApiTelematics extends BaiduApiServer {
	
	private GpsSignalPath signal = null;
	
	private List<GpsSignalPath> signalList = new ArrayList<GpsSignalPath>();
	
	@Override
	public void run() {
//		initMap();
		try {
			doTelematics();
		} finally {
			Thread.currentThread().interrupt();
		}
	}
	
	@Override
	public void callBack(String json) {
		Logger.println("Do Telematics at " + new Date());
		String status = null;
		try {
			Pattern p = Pattern.compile("\"status\":\"(?<status>\\w+)\"");
			Matcher m = p.matcher(json);
			if (m.find()) {
				status = m.group("status");
				if ("Success".equals(status)) {
					p = Pattern.compile("(?<point>\\d+\\.\\d+,\\d+\\.\\d+)");
					m = p.matcher(json);
					int j = 0;
					while (m.find()) {
						GpsSignalPath sg = (GpsSignalPath) signal.clone();
						String[] point = m.group("point").split(",");
						sg.baiduLng = Double.parseDouble(point[0]);
						sg.baiduLat = Double.parseDouble(point[1]);
						sg.sequence = j;
						signalList.add(sg);
						j++;
					}
				}else if("302".equals(status)){
					if(signalList.size()>0){
						Vehicle v = CacheManager.instance().getVehicle(signal.deviceNo);
						DbManager.instance().dbs.batchSaveGPSSignalPaths(signalList,v.company);
//						CacheManager.instance().getSignalPathQueue(v.company).addAll(signalList);
						signalList.clear();
					}
					CacheManager.instance().canDoPoint = false;
					Logger.err("坐标补点超出每日限额次数,处理中断");
					Thread.currentThread().interrupt();
				}
			}
		} catch (Exception e) {
			Logger.err(e);
			Logger.err(json);
		}
	}
	
	public void doTelematics() {
		try {
			if (null == CacheManager.instance().vehicleMap || 0 == CacheManager.instance().vehicleMap.size())
				return;
			Collection<Vehicle> vehicles = CacheManager.instance().vehicleMap.values();
			Iterator<Vehicle> it = vehicles.iterator();
			Vehicle vehicle = null;
			GpsSignal front = null;
			GpsSignal behind = null;
			boolean isEnd = false;
			while (it.hasNext()) {
				vehicle = it.next();
				if (CacheManager.instance().getSignalForTelematicsQueue(vehicle.device.deviceNo).isEmpty()) 
					continue;
				do {
					if (null == front) {
						front = CacheManager.instance().getSignalForTelematicsQueue(vehicle.device.deviceNo).poll();
					} else {
						front = behind;
					}
					behind = CacheManager.instance().getSignalForTelematicsQueue(vehicle.device.deviceNo).poll();
					// 判断管道中是否还有数据
					isEnd = CacheManager.instance().getSignalForTelematicsQueue(vehicle.device.deviceNo).isEmpty();
					if (1 != front.accStatus || 1 != behind.accStatus)
						// 前后两条数据acc必须都通电
						continue;
					long timeDiff = (behind.gpsTime.getTime() - front.gpsTime.getTime()) / 1000;
					double distance = Tools.getTwoPointDistance(
							front.baiduLng, front.baiduLat, behind.baiduLng, behind.baiduLat);
					if (timeDiff > 40 && distance > 100) {
						// 满足该条件，进行补点操作
						setCurrentGpsSignal(front);
						String uri = getUri(
								front.baiduLng, front.baiduLat, behind.baiduLng, behind.baiduLat);
						HttpClient client = new HttpClient();
						client.doRequest(uri, this);
					}
				} while (!isEnd);
				if (null != signalList && signalList.size() > 0) {
					DbManager.instance().dbs.batchSaveGPSSignalPaths(signalList, vehicle.company);
//					CacheManager.instance().getSignalPathQueue(vehicle.company).addAll(signalList);
					signalList.clear();
				}
			}
		} catch (Exception e) {
			Logger.err(e);
		}
	}
	
	/**
	 * 根据百度的起始坐标拼写uri
	 * 
	 * @param startlng
	 *            开始坐标的百度经度
	 * @param startlat
	 *            开始坐标的百度纬度
	 * @param endlng
	 *            结束坐标的百度经度
	 * @param endlat
	 *            结束坐标的百度纬度
	 * @param companyCode
	 *            公司代码
	 * @return uri
	 */
	private String getUri(double startlng, double startlat,
			double endlng, double endlat) {
		String baiduKey = ServerConfig.instance().api_baidukey;
		String place = CacheManager.instance().getVehicle(this.signal.deviceNo).company.place;
		if (place == null || place.trim().length() == 0) {
			place = "杭州";
		}
		StringBuilder builder = new StringBuilder();
		builder.append("http://api.map.baidu.com/telematics/v3/navigation?ak=");
		builder.append(baiduKey);
		builder.append("&origin=");
		builder.append(startlng);
		builder.append(",");
		builder.append(startlat);
		builder.append("&destination=");
		builder.append(endlng);
		builder.append(",");
		builder.append(endlat);
		builder.append("&region=");
		builder.append(place);
		builder.append("&output=json&coord_type=bd09ll&out_coord_type=bd09ll&route_type=1");
		return builder.toString();
	}

	private void setCurrentGpsSignal(GpsSignal s) {
		this.signal = new GpsSignalPath();
		signal.signalId = s.signalId;
		signal.deviceNo = s.gpsNo;
		signal.gpsTime = s.gpsTime;
		signal.baiduLng = s.baiduLng;
		signal.baiduLat = s.baiduLat;
		signal.companyCode = s.companyCode;
		signal.equipmentId = s.equipmentId;
		signal.sequence = 0;
		signal.accStatus = s.accStatus;
		signal.isInWork = s.isInWork;
		signal.speed = (int) s.speed;
		signal.totalMile = s.totalMile;
		signal.hasAlarm = s.hasAlarm;
		signal.todayMile = s.todayMile;
	}
	
}
